package com.xiaoyu.awakening.ai.evaluation.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoyu.awakening.ai.evaluation.dao.AwkEvalMapper;
import com.xiaoyu.awakening.ai.evaluation.dto.CreateSingleEvalTaskDTO;
import com.xiaoyu.awakening.ai.evaluation.dto.EvalCallbackDTO;
import com.xiaoyu.awakening.ai.evaluation.dto.EvalDataSetGenerateContext;
import com.xiaoyu.awakening.ai.evaluation.dto.EvalTaskQueryDTO;
import com.xiaoyu.awakening.ai.evaluation.entity.AwkEvalEntity;
import com.xiaoyu.awakening.ai.evaluation.enums.EvalStatusEnums;
import com.xiaoyu.awakening.ai.evaluation.feign.RagEvalProvider;
import com.xiaoyu.awakening.ai.evaluation.service.IAwkEvalDataSetService;
import com.xiaoyu.awakening.ai.evaluation.service.IAwkEvalService;
import com.xiaoyu.awakening.common.core.dto.Result;
import jakarta.annotation.Resource;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * ForgeEvalServiceImpl
 *
 * @author wangxiaoyu
 * @date 2025/8/20 16:05
 * @since v1.0
 */
@Service
@Log4j2
public class AwkEvalServiceImpl extends ServiceImpl<AwkEvalMapper, AwkEvalEntity> implements IAwkEvalService {
    @Resource
    private AwkEvalMapper forgeEvalMapper;

    public Map<String, IAwkEvalDataSetService> forgeEvalDataSetServiceFactory;

    @Autowired
    public AwkEvalServiceImpl(Map<String, IAwkEvalDataSetService> forgeEvalDataSetServiceFactory) {
        this.forgeEvalDataSetServiceFactory = forgeEvalDataSetServiceFactory;
    }

    @Resource
    @Lazy
    private RagEvalProvider ragEvalProvider;

    @Override
    public AwkEvalEntity createSingleEvalTask(CreateSingleEvalTaskDTO createSingleEvalTaskDTO) {

        String evalTaskCode = "FORGE-EVAL-" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + "-" + new Random(4).nextInt(1000, 9999);
        createSingleEvalTaskDTO.setTaskCode(evalTaskCode);

        Assert.isTrue(forgeEvalDataSetServiceFactory.containsKey(createSingleEvalTaskDTO.getDataSetExecutor()), "评测数据集执行器不存在");
        IAwkEvalDataSetService forgeEvalDataSetService = forgeEvalDataSetServiceFactory.get(createSingleEvalTaskDTO.getDataSetExecutor());
        EvalDataSetGenerateContext evalDataSetGenerateContext = forgeEvalDataSetService.generate(createSingleEvalTaskDTO);

        Assert.isFalse(Objects.isNull(evalDataSetGenerateContext), "评测数据集生成上下文为空");
        Assert.isFalse(Objects.isNull(evalDataSetGenerateContext.getSamples()) || CollectionUtil.isEmpty(evalDataSetGenerateContext.getSamples()), "评测数据集样本为空");
        Assert.isFalse(evalDataSetGenerateContext.getSamples().size() > 100, "评测数据集样本数量不能超过100条");
        evalDataSetGenerateContext.setTaskCode(evalTaskCode);
        evalDataSetGenerateContext.setMetrics(createSingleEvalTaskDTO.getMetrics());

        AwkEvalEntity forgeEvalEntity = new AwkEvalEntity();
        forgeEvalEntity.setEvalTaskName(createSingleEvalTaskDTO.getEvalTaskName());
        forgeEvalEntity.setEvalTaskDesc(createSingleEvalTaskDTO.getEvalTaskDesc());
        forgeEvalEntity.setType(createSingleEvalTaskDTO.getType());
        forgeEvalEntity.setUserId(createSingleEvalTaskDTO.getUserId());
        forgeEvalEntity.setDirId(createSingleEvalTaskDTO.getDirId());
        forgeEvalEntity.setFileIdList(JSON.toJSONString(createSingleEvalTaskDTO.getFileIdList()));
        forgeEvalEntity.setCreateTime(new Date());
        forgeEvalEntity.setDataset(JSON.toJSONString(evalDataSetGenerateContext));
        forgeEvalEntity.setStatus(EvalStatusEnums.CREATE.getCode());
        forgeEvalEntity.setEvalCode(evalTaskCode);
        forgeEvalEntity.setQaPair(JSON.toJSONString(evalDataSetGenerateContext.getQaPairDTOList()));
        this.save(forgeEvalEntity);
        
        // 评测任务提交评测引擎
        Result<String> evalRes;
        try {
            evalRes = ragEvalProvider.eval(createSingleEvalTaskDTO.getToken(), evalDataSetGenerateContext);
            forgeEvalEntity.setStatus(evalRes.isSuccess() ? EvalStatusEnums.COMMIT.getCode() : EvalStatusEnums.FAIL.getCode());
            log.info("调用评测引擎成功：{}", JSON.toJSONString(evalRes));
        } catch (Exception e) {
            forgeEvalEntity.setStatus(EvalStatusEnums.FAIL.getCode());
            log.error("调用评测引擎失败", e);
        }
        this.updateById(forgeEvalEntity);
        forgeEvalEntity.setUpdateTime(new Date());
        return forgeEvalEntity;
    }

    /**
     * 评测任务查询
     *
     * @param evalTaskQueryDTO 评测任务查询
     */
    @Override
    public List<AwkEvalEntity> queryList(EvalTaskQueryDTO evalTaskQueryDTO) {
        QueryWrapper<AwkEvalEntity> queryWrapper = new QueryWrapper<>();
        if (evalTaskQueryDTO.getEvalTaskIdList() != null && !evalTaskQueryDTO.getEvalTaskIdList().isEmpty()) {
            queryWrapper.in("eval_task_id", evalTaskQueryDTO.getEvalTaskIdList());
        }
        if (evalTaskQueryDTO.getType() != null) {
            queryWrapper.eq("type", evalTaskQueryDTO.getType());
        }
        if (evalTaskQueryDTO.getUserId() != null) {
            queryWrapper.eq("user_id", evalTaskQueryDTO.getUserId());
        }
        if (evalTaskQueryDTO.getEvalTaskName() != null) {
            queryWrapper.like("eval_task_name", evalTaskQueryDTO.getEvalTaskName());
        }
        queryWrapper.orderByDesc("create_time");
        queryWrapper.last("limit 100");
        return this.list(queryWrapper);
    }

    /**
     * 评测任务回调
     *
     * @param evalCallbackDTO 评测任务回调
     */
    @Override
    public void callback(EvalCallbackDTO evalCallbackDTO) {
        AwkEvalEntity forgeEvalEntity = this.getOne(new LambdaQueryWrapper<AwkEvalEntity>().eq(AwkEvalEntity::getEvalCode, evalCallbackDTO.getEvalCode()));
        Assert.isFalse(Objects.isNull(forgeEvalEntity), "评测任务不存在");
        forgeEvalEntity.setStatus(EvalStatusEnums.COMPLETE.getCode());
        forgeEvalEntity.setEvalResult(evalCallbackDTO.getEvalResult());
        forgeEvalEntity.setEvalResultUrl(evalCallbackDTO.getEvalResultUrl());
        forgeEvalEntity.setUpdateTime(new Date());
        this.updateById(forgeEvalEntity);
    }
}
